package jxtend.processor.eclipse.visitor.traverser;

import jxtend.processor.eclipse.utils.ASTNodeUtils;
import jxtend.processor.eclipse.visitor.ASTNodeScopeFactory;
import jxtend.processor.reflect.ReflectField;

import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.ForeachStatement;
import org.eclipse.jdt.internal.compiler.ast.Statement;
import org.eclipse.jdt.internal.compiler.lookup.BlockScope;

@SuppressWarnings("restriction")
public class ForeachStatementTraverser implements ASTNodeChildrenTraverser {

	@Override
	public boolean isApplicable(ASTNode node) {
		return (node instanceof ForeachStatement);
	}

	@Override
	public void traverseChildren(ASTNode node, ASTVisitor visitor, BlockScope scope) {
		ForeachStatement foreachStatement = (ForeachStatement) node;

		ASTNodeUtils.traverseNullableNode(foreachStatement.collection, visitor, foreachStatement.scope);

		foreachStatement.elementVariable.traverse(visitor, foreachStatement.scope);

		Statement actionStatement = foreachStatement.action;

		if (actionStatement != null) {
			Class<Statement> actionStatementType = ASTNodeUtils.getClassForNormalKindASTNode(foreachStatement.action);
			ReflectField<Statement, BlockScope> scopeFieldOfActionStatement =
				ReflectField.findField(actionStatementType, BlockScope.class, "scope");

			BlockScope actionStatementScope;
			if (scopeFieldOfActionStatement != null) {
				actionStatementScope = scopeFieldOfActionStatement.get(actionStatement);
				if (actionStatementScope == null && foreachStatement.scope != null) {
					actionStatementScope = (BlockScope) ASTNodeScopeFactory.create(
							actionStatement, scopeFieldOfActionStatement, foreachStatement.scope);
					scopeFieldOfActionStatement.set(actionStatement, actionStatementScope);
				}
			} else {
				actionStatementScope = foreachStatement.scope;
			}

			actionStatement.traverse(visitor, actionStatementScope);
		}
	}

}
